﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using RapidSalesAdminPortalAPI.DataAccess;
using RapidSalesAdminPortalAPI.Models;
using RapidSalesAdminPortalAPI.Services;
using ServiceReference1;
using System.Collections.Generic;
using System.Data;
using WebAPI.Common;
using WebAPI.Common.Attributes;
using WebAPI.Controllers;
using WebAPI.Models;
using WebAPI.Services;
using WebAPI.Util;
using static WebAPI.Models.Enums;

namespace RapidSalesAdminPortalAPI.Controllers
{
    /// <summary>
    /// H5-产品
    /// </summary>
    [Route("api/[controller]")]
    [ApiController]
    public class ProductFrontController : ParentFrontController
    {
        private readonly RS_AdmPortalContext _context;
        private readonly IConfiguration _configuration;
        private readonly ILogUtility _logUtility;
        private readonly ILogger _logger;
        private readonly IDataProtectorUtility _dataProtectorUntility;
        private readonly ISoapService _soapService;

        public ProductFrontController(RS_AdmPortalContext context, IConfiguration configuration, ILogUtility logUtility, ILogger<ProductController> logger, IDataProtectorUtility dataProtectorUntility, ISoapService soapService)
        {
            _context = context;
            _configuration = configuration;
            _logUtility = logUtility; // sample code for DI of common utility class
            _logger = logger;
            _dataProtectorUntility = dataProtectorUntility;
            _soapService = soapService;
        }

        [HttpPost("GetProductList")]
        public async Task<ActionResult<ResultMsg>> GetProductList([FromBody] GetProductListFrontRequest requestModel)
        {
            var resultMsg = new ResultMsg();
            try
            {
                List<GetProductListFrontResponse> returnList = new List<GetProductListFrontResponse>();
                var sql = $@"select e.Id as EventId, e.EventCode,e.EventAK,e.EventName_EN,e.EventName_SC,e.EventName_TC,e.EventName_OT,e.EventDescription_EN,e.EventDescription_SC,e.EventDescription_TC,e.EventDescription_OT
,p.Id,p.ProductCode,p.UnitPrice,p.ProductName_EN,p.ProductName_SC,p.ProductName_TC,p.ProductName_OT,p.Thumbnail,p.TicketDescription_EN,p.TicketDescription_SC,p.TicketDescription_TC,p.TicketDescription_OT,p.MaxPurchaseQty
,p.IsRequired,spp.CutOffTime, p.MatrixCellAK as MatrixCellAK
from FR_IP_SalesPoint sp with(nolock)
inner join FR_IP_SalesPointProducts spp with(nolock) on spp.SalesPointId=sp.Id
inner join FR_IP_ProductEvents pe with(nolock) on pe.id=spp.ProductEvenetId
inner join FR_IP_Event e with(nolock) on e.Id=pe.EventId and e.Enable=1
inner join FR_IP_Product p with(nolock) on p.Id=pe.ProductId and p.Enable=1
where sp.IsDelete=0 and sp.Enable=1 and sp.Code=@SalesPointCode";
                var param = new SqlParameter[1];
                param[0] = new SqlParameter()
                {
                    ParameterName = "@SalesPointCode",
                    SqlDbType = SqlDbType.NVarChar,
                    Size = 200,
                    Value = requestModel.SalesPointCode,
                };
                var dbList = _context.ProductListFrontModel.FromSqlRaw(sql, param).ToList();
                if (dbList != null && dbList.Count > 0)
                {
                    var groups = dbList.GroupBy(x => x.EventId).Distinct().ToList();
                    foreach (var group in groups) 
                    { 
                        var gList = group.ToList();
                        var firstModel = gList.FirstOrDefault();
                        if (firstModel == null)
                            continue;

                        //event
                        var now = DateTime.Now;
                        string eventId = firstModel.EventId.ToString();
                        string eventName = "";
                        string eventDesc = "";
                        switch (requestModel.lang)
                        {
                            case (int)LanguageType.SC:
                                eventName = firstModel.EventName_SC;
                                eventDesc = firstModel.EventDescription_SC;
                                break;
                            case (int)LanguageType.TC:
                                eventName = firstModel.EventName_TC;
                                eventDesc = firstModel.EventDescription_TC;
                                break;
                            case (int)LanguageType.OT:
                                eventName = firstModel.EventName_OT;
                                eventDesc = firstModel.EventDescription_OT;
                                break;
                            case (int)LanguageType.En:
                            default:
                                eventName = firstModel.EventName_EN;
                                eventDesc = firstModel.EventDescription_EN;
                                break;
                        }

                        //product
                        List<GetProductListFrontResponse_ProductList> pList = new List<GetProductListFrontResponse_ProductList>();
                        List<GetProductListFrontResponse_EventTimeSlotsList> timeslotsList = new List<GetProductListFrontResponse_EventTimeSlotsList>();
                        foreach (var item in gList)
                        {
                            bool isOk = false;
                            string pId = item.Id.ToString();
                            var isRequest = item.IsRequired;
                            if (!isRequest)
                                isOk = true;
                            else
                            {
                                int cutofftime = item.CutOffTime;
                                #region query EventTimeSlots
                                //query local
                                IQueryable<FrIpEventTimeSlot> tsList = _context.FrIpEventTimeSlots.AsQueryable();
                                tsList = tsList.Where(x => x.EventId == new Guid(eventId));
                                var tsData = await tsList.ToListAsync();

                                //query remote
                                //var tsData = await _soapService.SearchPerformance(item.EventAK);
                                if (tsData != null && tsData.Count > 0)
                                {
                                    foreach (var t in tsData)
                                    {
                                        if (t.IsFullDay.GetValueOrDefault())
                                            continue;
                                        if (string.IsNullOrWhiteSpace(t.OpeningTime))
                                            continue;

                                        if (!string.IsNullOrWhiteSpace(t.OpeningTime))
                                        {
                                            int hour = 0;
                                            var htext = t.OpeningTime.Trim().Substring(0, 2);
                                            int.TryParse(htext, out hour);
                                            if (hour > 0)
                                            {
                                                int h = hour - cutofftime;
                                                if (now.Hour < h)
                                                {
                                                    isOk = true;
                                                    //break;

                                                    //EventTimeSlot
                                                    timeslotsList.Add(new GetProductListFrontResponse_EventTimeSlotsList()
                                                    {
                                                        //Id = t.Id.ToString(),
                                                        OpeningTime = !string.IsNullOrWhiteSpace(t.OpeningTime) ? t.OpeningTime.Substring(0, 5) : "",
                                                        ClosingTime = !string.IsNullOrWhiteSpace(t.ClosingTime) ? t.ClosingTime.Substring(0, 5) : "",
                                                    });
                                                }
                                            }
                                        }
                                    }
                                }
                                #endregion
                            }

                            if (isOk)
                            {
                                string pCode = item.ProductCode;
                                string pThumbnail = item.Thumbnail;
                                decimal pUnitPrice = item.UnitPrice;
                                int pMaxPurchaseQty = item.MaxPurchaseQty.GetValueOrDefault();
                                string pName = "";
                                string pTicketDescription = "";
                                switch (requestModel.lang)
                                {
                                    case (int)LanguageType.SC:
                                        pName = item.ProductName_SC;
                                        pTicketDescription = item.TicketDescription_SC;
                                        break;
                                    case (int)LanguageType.TC:
                                        pName = firstModel.ProductName_TC;
                                        pTicketDescription = firstModel.TicketDescription_TC;
                                        break;
                                    case (int)LanguageType.OT:
                                        pName = firstModel.ProductName_OT;
                                        pTicketDescription = firstModel.TicketDescription_OT;
                                        break;
                                    case (int)LanguageType.En:
                                    default:
                                        pName = firstModel.ProductName_EN;
                                        pTicketDescription = firstModel.TicketDescription_EN;
                                        break;
                                }

                                pList.Add(new GetProductListFrontResponse_ProductList()
                                {
                                    ProductId = pId,
                                    ProductCode = pCode,
                                    Thumbnail = pThumbnail,
                                    UnitPrice = pUnitPrice,
                                    MaxPurchaseQty = pMaxPurchaseQty,
                                    ProductName = pName,
                                    TicketDescription = pTicketDescription,
                                    Number = 0,
                                });
                            }
                        }

                        if (timeslotsList != null && timeslotsList.Count > 0)
                        {
                            timeslotsList = timeslotsList.OrderBy(x => x.OpeningTime).ToList();
                        }

                        if (pList != null && pList.Count > 0)
                        {
                            returnList.Add(new GetProductListFrontResponse()
                            {
                                EventId = eventId,
                                EventName = eventName,
                                EventDesc = eventDesc,
                                ProductList = pList,
                                TimeSlotsList = timeslotsList,
                            });
                        }
                    }
                }

                return resultMsg.SetResultMsg(
                     (int)ResultCode.Success,
                     HelperUtility.GetDescription(ResultCode.Success),
                     returnList);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.Message);
                return resultMsg.SetResultMsg(
                     (int)ResultCode.ErrorOnRequestUnMarshalling,
                     HelperUtility.GetDescription(ResultCode.ErrorOnRequestUnMarshalling),
                     ex.Message);
            }
        }

        [HttpPost("AddContactInfo")]
        public async Task<ActionResult<ResultMsg>> AddContactInfo([FromBody] AddContactInfoRequest requestModel)
        {
            var resultMsg = new ResultMsg();
            try
            {
                #region check params
                //if (string.IsNullOrWhiteSpace(requestModel.SalesPointId))
                //{
                //    return resultMsg.SetResultMsg(
                //     (int)ResultCode.NoDataFound,
                //     HelperUtility.GetDescription(ResultCode.FieldRequired),
                //     "Sales Point Id is none");
                //}
                //if (string.IsNullOrWhiteSpace(requestModel.LastName))
                //{
                //    return resultMsg.SetResultMsg(
                //     (int)ResultCode.NoDataFound,
                //     HelperUtility.GetDescription(ResultCode.FieldRequired),
                //     "Last Name is none");
                //}
                //if (string.IsNullOrWhiteSpace(requestModel.FirstName))
                //{
                //    return resultMsg.SetResultMsg(
                //     (int)ResultCode.NoDataFound,
                //     HelperUtility.GetDescription(ResultCode.FieldRequired),
                //     "First Name is none");
                //}
                //if (string.IsNullOrWhiteSpace(requestModel.ContactNumber))
                //{
                //    return resultMsg.SetResultMsg(
                //     (int)ResultCode.NoDataFound,
                //     HelperUtility.GetDescription(ResultCode.FieldRequired),
                //     "Contact Number is none");
                //}
                //if (string.IsNullOrWhiteSpace(requestModel.Email))
                //{
                //    return resultMsg.SetResultMsg(
                //     (int)ResultCode.NoDataFound,
                //     HelperUtility.GetDescription(ResultCode.FieldRequired),
                //     "Email is none");
                //}
                #endregion

                //insert data
                DateTime NowTime = DateTime.Now;
                Guid Id = Guid.NewGuid();
                FrIpTransactionHistory dt = new FrIpTransactionHistory()
                {
                    Id = Id,
                    SalesPointId = new Guid(requestModel.SalesPointId),
                    GuestName = requestModel.FirstName + " " + requestModel.LastName,
                    GuestContactNumber = requestModel.ContactNumber,
                    GuestEmail = requestModel.Email,
                    LastUpdatedOn = NowTime,
                };
                _context.FrIpTransactionHistories.Add(dt);
                await _context.SaveChangesAsync();

                //Success
                return resultMsg.SetResultMsg(
                (int)ResultCode.Success,
                HelperUtility.GetDescription(ResultCode.Success),
                Id);
            }
            catch (Exception ex)
            {
                _logger.LogError("ProductFront/AddContactInfo Error:" + ex.Message);
                return resultMsg.SetResultMsg(
                 (int)ResultCode.ErrorOnRequestUnMarshalling,
                 HelperUtility.GetDescription(ResultCode.ErrorOnRequestUnMarshalling),
                 null);
            }
        }

        // in CommonController/CheckOutProducts
        //[HttpPost("CheckOutProducts")]
        //public async Task<ActionResult<ResultMsg>> CheckOutProducts([FromBody] CheckOutProductsRequest requestModel)
        //{
        //    var resultMsg = new ResultMsg();
        //    try
        //    {
        //        if (string.IsNullOrWhiteSpace(requestModel.ProductList))
        //        {
        //            return resultMsg.SetResultMsg(
        //             (int)ResultCode.NoDataFound,
        //             HelperUtility.GetDescription(ResultCode.FieldRequired),
        //             "ProductList is none");
        //        }

        //        List<CheckOutProductsRequest_ProductInfo> list = JsonConvert.DeserializeObject<List<CheckOutProductsRequest_ProductInfo>>(requestModel.ProductList);
        //        List<CheckOutProductsResponse> rList = new List<CheckOutProductsResponse>();
        //        List<ProductEventReqeust> productEventList = new List<ProductEventReqeust>();
        //        foreach (var item in list)
        //        {
        //            var p = await _context.FrIpProducts.FindAsync(new Guid(item.ProductId));
        //            if (p == null)
        //            {
        //                rList.Add(new CheckOutProductsResponse()
        //                {
        //                    Type = 2,
        //                    ProductId = item.ProductId,
        //                    ProductName = item.ProductName,
        //                });                        
        //            }
        //            else {
        //                productEventList.Add(new ProductEventReqeust() {
        //                    MatrixCellAK = p.MatrixCellAk,
        //                    IsRequired = p.IsRequired.GetValueOrDefault(),
        //                    Qty = item.ProductNum.ToString(),
        //                });


        //            }
        //        }

        //        if (productEventList != null && productEventList.Count > 0)
        //        {


        //            //if (p.MaxPurchaseQty < item.ProductNum)
        //            //{
        //            //    rList.Add(new CheckOutProductsResponse()
        //            //    {
        //            //        Type = 1,
        //            //        ProductId = item.ProductId,
        //            //        ProductName = item.ProductName,
        //            //        CurrentNum = p.MaxPurchaseQty.GetValueOrDefault(),
        //            //    });
        //            //}
        //        }

        //        return resultMsg.SetResultMsg(
        //        (int)ResultCode.Success,
        //        HelperUtility.GetDescription(ResultCode.Success),
        //        rList);
        //    }
        //    catch (Exception ex)
        //    {
        //        _logger.LogError("ProductFront/CheckOutProducts Error:" + ex.Message);
        //        return resultMsg.SetResultMsg(
        //         (int)ResultCode.ErrorOnRequestUnMarshalling,
        //         HelperUtility.GetDescription(ResultCode.ErrorOnRequestUnMarshalling),
        //         ex.Message);
        //    }
        //}

        [HttpPost("CreateTransaction")]
        public async Task<ActionResult<ResultMsg>> CreateTransaction([FromBody] CreateTransactionRequest requestModel)
        {
            var resultMsg = new ResultMsg();
            try
            {
                var transactionHistoryModel = await _context.FrIpTransactionHistories.FindAsync(new Guid(requestModel.TransactionId));
                if (transactionHistoryModel == null)
                {
                    return resultMsg.SetResultMsg(
                     (int)ResultCode.NoDataFound,
                     HelperUtility.GetDescription(ResultCode.NoDataFound),
                     "transaction log is not found");
                }

                DateTime NowTime = DateTime.Now;
                var orderno = DateTime.Now.ToString("yyMMddHHmmssfff");
                //var orderno = Guid.NewGuid().ToString();
                transactionHistoryModel.LastUpdatedOn = NowTime;
                transactionHistoryModel.CheckOutTime = NowTime;
                transactionHistoryModel.CheckOutProducts = requestModel.Products;
                transactionHistoryModel.CheckOutAmount = requestModel.Amount;
                transactionHistoryModel.OrderNo = orderno;
                _context.Entry(transactionHistoryModel).State = EntityState.Modified;
                await _context.SaveChangesAsync();

                CreateTransactionResponse res = new CreateTransactionResponse();
                res.OrderNo = orderno;
                res.Amount = requestModel.Amount;

                return resultMsg.SetResultMsg(
                (int)ResultCode.Success,
                HelperUtility.GetDescription(ResultCode.Success),
                res);
            }
            catch (Exception ex)
            {
                _logger.LogError("ProductFront/CreateTransaction Error:" + ex.Message);
                return resultMsg.SetResultMsg(
                 (int)ResultCode.ErrorOnRequestUnMarshalling,
                 HelperUtility.GetDescription(ResultCode.ErrorOnRequestUnMarshalling),
                 ex.Message);
            }
        }

        [HttpPost("TestSearchPerformance")]
        public async Task<ActionResult<ResultMsg>> TestSearchPerformance(string EventAK)
        {
            var resultMsg = new ResultMsg();
            try
            {
                var tsData = await _soapService.SearchPerformance(EventAK);

                return resultMsg.SetResultMsg(
                (int)ResultCode.Success,
                HelperUtility.GetDescription(ResultCode.Success),
                tsData);
            }
            catch (Exception ex)
            {
                _logger.LogError("ProductFront/CreateTransaction Error:" + ex.Message);
                return resultMsg.SetResultMsg(
                 (int)ResultCode.ErrorOnRequestUnMarshalling,
                 HelperUtility.GetDescription(ResultCode.ErrorOnRequestUnMarshalling),
                 ex.Message);
            }
        }
 
    }
}
